﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Xml.Linq;

namespace HR_ParticleEditor
{
    public partial class Form1 : Form
    {

        List<Particle> m_vTotalParticles = new List<Particle>();
        public Random rnd = new Random();


        float m_fCurrLife;

        public float FCurrLife
        {
            get { return m_fCurrLife; }
            set { m_fCurrLife = value; }
        }

        bool m_bIsLooping;

        public bool BIsLooping
        {
            get { return m_bIsLooping; }
            set { m_bIsLooping = value; }
        }

        int m_nPartImageID;

        public int NPartImageID
        {
            get { return m_nPartImageID; }
            set { m_nPartImageID = value; }
        }

        float m_fPosX;

        public float FPosX
        {
            get { return m_fPosX; }
            set { m_fPosX = value; }
        }

        float m_fPosY;

        public float FPosY
        {
            get { return m_fPosY; }
            set { m_fPosY = value; }
        }
        // 1 = Circle, 0 = Square
        int m_nSpawnShape;

        public int NSpawnShape
        {
            get { return m_nSpawnShape; }
            set { m_nSpawnShape = value; }
        }

        float m_fSpawnRate;

        public float FSpawnRate
        {
            get { return m_fSpawnRate; }
            set { m_fSpawnRate = value; }
        }
        float m_fSpawnRange;

        public float FSpawnRange
        {
            get { return m_fSpawnRange; }
            set { m_fSpawnRange = value; }
        }


        //Start/End ARGB values
        int m_nStartAlpha;

        public int NStartAlpha
        {
            get { return m_nStartAlpha; }
            set { m_nStartAlpha = value; }
        }

        int m_nStartR;

        public int NStartR
        {
            get { return m_nStartR; }
            set { m_nStartR = value; }
        }
        int m_nStartG;

        public int NStartG
        {
            get { return m_nStartG; }
            set { m_nStartG = value; }
        }
        int m_nStartB;

        public int NStartB
        {
            get { return m_nStartB; }
            set { m_nStartB = value; }
        }
        float m_fStartVelX;

        public float FStartVelX
        {
            get { return m_fStartVelX; }
            set { m_fStartVelX = value; }
        }
        float m_fStartVelY;

        public float FStartVelY
        {
            get { return m_fStartVelY; }
            set { m_fStartVelY = value; }
        }
        float m_fStartRotation;

        public float FStartRotation
        {
            get { return m_fStartRotation; }
            set { m_fStartRotation = value; }
        }
        float m_fStartScale;

        public float FStartScale
        {
            get { return m_fStartScale; }
            set { m_fStartScale = value; }
        }

        int m_nEndAlpha;

        public int NEndAlpha
        {
            get { return m_nEndAlpha; }
            set { m_nEndAlpha = value; }
        }
        int m_nEndR;

        public int NEndR
        {
            get { return m_nEndR; }
            set { m_nEndR = value; }
        }
        int m_nEndG;

        public int NEndG
        {
            get { return m_nEndG; }
            set { m_nEndG = value; }
        }
        int m_nEndB;

        public int NEndB
        {
            get { return m_nEndB; }
            set { m_nEndB = value; }
        }
        float m_fEndVelX;

        public float FEndVelX
        {
            get { return m_fEndVelX; }
            set { m_fEndVelX = value; }
        }
        float m_fEndVelY;

        public float FEndVelY
        {
            get { return m_fEndVelY; }
            set { m_fEndVelY = value; }
        }
        float m_fEndRotation;

        public float FEndRotation
        {
            get { return m_fEndRotation; }
            set { m_fEndRotation = value; }
        }
        float m_fEndScale;

        public float FEndScale
        {
            get { return m_fEndScale; }
            set { m_fEndScale = value; }
        }

        string NameOfParticle;

        public string NameOfParticle1
        {
            get { return NameOfParticle; }
            set { NameOfParticle = value; }
        }

        int m_nNumOfParticles;

        public int NNumOfParticles
        {
            get { return m_nNumOfParticles; }
            set { m_nNumOfParticles = value; }
        }

        // SGP C# wrappers
        SGP.CSGP_Direct3D m_D3D = null;
        SGP.CSGP_TextureManager m_TM = null;

        // Game time
        float m_fTimer = 0;

        bool looping = true;

        public bool Looping
        {
            get { return looping; }
            set { looping = value; }
        }

        // Application running flag property
        public bool Running
        {
            get;
            set;
        }

        //Bitmap IMAGE = new Bitmap("../Resource/Graphics/PlaceholderImage.png");

        public Form1()
        {
            // Initialize form components
            InitializeComponent();
            this.Focus();


            // Change the Current Working Directory out of the 'bin\Debug\' or 'bin\Release\' folders
            string dir = System.IO.Directory.GetCurrentDirectory();
            int index = dir.LastIndexOf("bin\\Debug");
            if (index != -1)
                dir = dir.Remove(index);
            index = dir.LastIndexOf("bin\\Release");
            if (index != -1)
                dir = dir.Remove(index);

            System.IO.Directory.SetCurrentDirectory(dir);

            // Store the Current Working Directory in the text box
            textBox1.Text = System.IO.Directory.GetCurrentDirectory();

           
        }

        ////////////////////////////////////////////////////////////////////////////////
        // Initialize
        //	- initialize the SGP wrappers
        //	- load assets
        ////////////////////////////////////////////////////////////////////////////////
        public void Initialize()
        {
            // Access the SGP Wrapper singletons
            m_D3D = SGP.CSGP_Direct3D.GetInstance();
            m_TM = SGP.CSGP_TextureManager.GetInstance();

            // Initialize the Direct3D render targets
            m_D3D.Initialize(ImagePanel, false);
            m_D3D.AddRenderTarget(ImagePanel);

            m_D3D.Initialize(EmitterPanel, false);
            m_D3D.AddRenderTarget(EmitterPanel);

            // Initialize the Texture Manager
            m_TM.Initialize(m_D3D.Device, m_D3D.Sprite);

            OpenFileDialog dlg = new OpenFileDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
               // bitmap = new Bitmap(dlg.FileName);
               // m_nPartImageID = m_TM.LoadTexture("Resource/Graphics/PlaceholderImage.png");	// w/o color key
                NameOfParticle = dlg.SafeFileName;
                m_nPartImageID = m_TM.LoadTexture(dlg.FileName);	// w/o color key
            }

            // Load assets
            

            m_bIsLooping = true;
            m_fCurrLife = 2.0f;
            m_fPosX = 300;
            m_fPosY = 300;
            m_nSpawnShape = 0;
            m_fSpawnRate = 0.01f;
            m_fSpawnRange = 1.0f;
            m_nStartAlpha = 255;
            m_nEndAlpha = 255;
            m_nStartR = 255;
            m_nEndR = 255;
            m_nStartG = 255;
            m_nEndG = 0;
            m_nStartB = 0;
            m_nEndB = 0;
            m_fStartVelX = 30.0f;
            m_fEndVelX = 50.0f;
            m_fStartVelY = 30.0f;
            m_fEndVelY = -50.0f;
            m_fStartRotation = 0.0f;
            m_fEndRotation = 0.0f;
            m_fStartScale = 0.5f;
            m_fEndScale = 0.5f;
            m_nNumOfParticles = 1000;


            numericUpDown2.Value = m_vTotalParticles.Count();
            numericUpDown1.Value = (int)m_fCurrLife;
            // success.
            Running = true;
        }


        ////////////////////////////////////////////////////////////////////////////////
        // Terminate
        //	- unload assets
        //	- terminate the SGP wrappers
        ////////////////////////////////////////////////////////////////////////////////
        public void Terminate()
        {


            // Shut down the wrappers
            m_TM.Terminate();
            m_D3D.Terminate();
        }


        ////////////////////////////////////////////////////////////////////////////////
        // Form1_FormClosing
        //	- triggered when the form is about to be closed (after the close button is clicked)
        //	- sets flag to tell main loop to quit
        ////////////////////////////////////////////////////////////////////////////////
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Running = false;
        }


        public void Update(float fElapsedTime)
        {
            // Update global timer
            m_fTimer += fElapsedTime;

             for (int ParticleIndex = 0; ParticleIndex < m_nNumOfParticles; ParticleIndex++)
             {
                 if (m_nNumOfParticles > m_vTotalParticles.Count && m_fTimer >= m_fSpawnRate)
                 {
                     m_fTimer = 0.0f;
                      Particle newPart = new Particle(); 
                      newPart.ParentEmitter1 = this;
                     newPart.Renew();
                     m_vTotalParticles.Add(newPart);
                 }
                 else if (ParticleIndex < m_vTotalParticles.Count && m_vTotalParticles[ParticleIndex].FCurrentLife > 0.0f)
                 {
                     m_vTotalParticles[ParticleIndex].Update(fElapsedTime);
                 }
                 else if (ParticleIndex < m_vTotalParticles.Count && m_bIsLooping)
                 {
                     m_vTotalParticles[ParticleIndex].Renew();
                 }
                 //else
                 //    RemoveParticle(ParticleIndex);
             }

             numericUpDown2.Value = m_vTotalParticles.Count();
         }

        public void Render()
        {
            m_D3D.Clear(EmitterPanel, Color.Black);
            m_D3D.DeviceBegin();
            m_D3D.SpriteBegin();

            for (int ParticleIndex = 0; ParticleIndex < m_vTotalParticles.Count(); ParticleIndex++)
            {
                if (m_vTotalParticles[ParticleIndex].FCurrentLife > 0.0f)
                {
                    Rectangle rect = new Rectangle(0, 0, 64, 64);

                    m_TM.Draw(m_nPartImageID, 
                        (int)m_vTotalParticles[ParticleIndex].FPosX, 
                        (int)m_vTotalParticles[ParticleIndex].FPosY,
                        m_vTotalParticles[ParticleIndex].FScale, 
                        m_vTotalParticles[ParticleIndex].FScale, 
                        rect, 
                        0,
                       0, 
                       m_vTotalParticles[ParticleIndex].FRotation, 
                       Color.FromArgb(m_vTotalParticles[ParticleIndex].NColorA, m_vTotalParticles[ParticleIndex].NColorR, m_vTotalParticles[ParticleIndex].NColorG, m_vTotalParticles[ParticleIndex].NColorB));
                }
            }


            m_D3D.SpriteEnd();
            m_D3D.DeviceEnd();
            m_D3D.Present();


            m_D3D.Clear(ImagePanel, Color.Chocolate);
            m_D3D.DeviceBegin();
            m_D3D.SpriteBegin();

            m_TM.Draw(m_nPartImageID, 50, 50);

            m_D3D.SpriteEnd();
            m_D3D.DeviceEnd();

            m_D3D.Present();
        }


        public void RemoveParticle(int INDEX)
        {
            m_vTotalParticles.RemoveAt(INDEX);
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            m_fCurrLife = (float)numericUpDown1.Value;
        }

        private void newImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                m_nPartImageID = m_TM.LoadTexture(dlg.FileName);	// w/o color key
            }
        }

        private void buttonLoadNewImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                m_nPartImageID = m_TM.LoadTexture(dlg.FileName);	// w/o color key
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            dlg.DefaultExt = "xml";

            int loop = 0;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement xRoot = new XElement("Total_Emitters");
 
                 XElement xEmitter= new XElement("Emitter");
                 xRoot.Add(xEmitter);

                 XElement PartVal = new XElement("TotalParticles");
                 xEmitter.Add(PartVal);
                     XAttribute PVal = new XAttribute("Value", m_nNumOfParticles);
                    PartVal.Add(PVal);

                 XElement Loop = new XElement("IsLooping");
                 xEmitter.Add(Loop);
                    
                if(m_bIsLooping)
                    loop = 1;
                else
                    loop = 0;
                    XAttribute LVal = new XAttribute("Value", loop);
                    Loop.Add(LVal);

                XElement Life = new XElement("Life");
                xEmitter.Add(Life);
                    XAttribute LifeVal = new XAttribute("Value", m_fCurrLife);
                    Life.Add(LifeVal);

                XElement SpawnRange = new XElement("SpawnRange");
                xEmitter.Add(SpawnRange);
                    XAttribute SpawnRgVal = new XAttribute("Value", m_fSpawnRange);
                    SpawnRange.Add(SpawnRgVal);

               XElement SpawnRate = new XElement("SpawnRate");
               xEmitter.Add(SpawnRate);
                    XAttribute SpawnRtVal = new XAttribute("Value", m_fSpawnRate);
                    SpawnRate.Add(SpawnRtVal);

               XElement Velx = new XElement("VelocityX");
               xEmitter.Add(Velx);
                    XAttribute VelxStart = new XAttribute("Start", m_fStartVelX);
                    Velx.Add(VelxStart);
                    XAttribute VelxEnd = new XAttribute("End", m_fEndVelX);
                    Velx.Add(VelxEnd);

               XElement Vely = new XElement("VelocityY");
               xEmitter.Add(Vely);
                    XAttribute VelyStart = new XAttribute("Start", m_fStartVelY);
                    Vely.Add(VelyStart);
                    XAttribute VelyEnd = new XAttribute("End", m_fEndVelY);
                    Vely.Add(VelyEnd);

               XElement Rotation = new XElement("Rotation");
               xEmitter.Add(Rotation);
                    XAttribute RotS = new XAttribute("Start", m_fStartRotation);
                    Rotation.Add(RotS);
                    XAttribute RotE = new XAttribute("End", m_fEndRotation);
                    Rotation.Add(RotE);

               XElement Scale = new XElement("Scale");
               xEmitter.Add(Scale);
                    XAttribute ScaleSt = new XAttribute("Start", m_fStartScale);
                    Scale.Add(ScaleSt);
                    XAttribute ScaleEnd = new XAttribute("End", m_fEndScale);
                    Scale.Add(ScaleEnd);

               XElement Position = new XElement("Position");
               xEmitter.Add(Position);
                    XAttribute Posx = new XAttribute("X", m_fPosX);
                    Position.Add(Posx);
                    XAttribute Posy = new XAttribute("Y", m_fPosY);
                    Position.Add(Posy);

              XElement ImageID = new XElement("ImageID");
              xEmitter.Add(ImageID);
                    XText ImageVal = new XText(NameOfParticle);
                    ImageID.Add(ImageVal);

              XElement SpawnShape = new XElement("SpawnShape");
              xEmitter.Add(SpawnShape);
                    XAttribute SpawnSpVal = new XAttribute("Value", m_nSpawnShape);
                    SpawnShape.Add(SpawnSpVal);

              XElement Alpha = new XElement("Alpha");
              xEmitter.Add(Alpha);
                    XAttribute AlStart = new XAttribute("Start", m_nStartAlpha);
                    Alpha.Add(AlStart);
                    XAttribute AlEnd = new XAttribute("End", m_nEndAlpha);
                    Alpha.Add(AlEnd);

             XElement Red = new XElement("Red");
             xEmitter.Add(Red);
                    XAttribute RedS = new XAttribute("Start", m_nStartR);
                    Red.Add(RedS);
                    XAttribute RedE = new XAttribute("End", m_nStartR);
                    Red.Add(RedE);


             XElement Green = new XElement("Green");
             xEmitter.Add(Green);
                    XAttribute GreenS = new XAttribute("Start", m_nStartG);
                    Green.Add(GreenS);
                    XAttribute GreenE = new XAttribute("End", m_nEndG);
                    Green.Add(GreenE);


             XElement Blue = new XElement("Blue");
             xEmitter.Add(Blue);
                    XAttribute BlueS = new XAttribute("Start", m_nStartB);
                    Blue.Add(BlueS);
                    XAttribute BlueE = new XAttribute("End", m_nEndB);
                    Blue.Add(BlueE);

                xRoot.Save(dlg.FileName);
            }
        }

        private void existingEmitterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;

            int loop = 0;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement xRoot = XElement.Load(dlg.FileName);

                XElement xEmitter = xRoot.Element("Emitter");

                XElement PartVal = xEmitter.Element("TotalParticles");
                XAttribute PVal = PartVal.Attribute("Value");
                m_nNumOfParticles = int.Parse(PVal.Value);

                XElement Loop = xEmitter.Element("IsLooping");
                XAttribute LVal = Loop.Attribute("Value");
                loop = int.Parse(LVal.Value);
                if (loop == 1)
                    m_bIsLooping = true;
                else
                    m_bIsLooping = false;

                XElement Life = xEmitter.Element("Life");
                XAttribute LifeVal = Life.Attribute("Value");
                m_fCurrLife = float.Parse(LifeVal.Value);

                XElement SpawnRange = xEmitter.Element("SpawnRange");
                XAttribute SpawnRgVal = SpawnRange.Attribute("Value");
                m_fSpawnRange = float.Parse(SpawnRgVal.Value);

                XElement SpawnRate = xEmitter.Element("SpawnRate");
                XAttribute SpawnRtVal = SpawnRate.Attribute("Value");
                m_fSpawnRate = float.Parse(SpawnRtVal.Value);

                XElement Velx = xEmitter.Element("VelocityX");
                XAttribute VelxStart = Velx.Attribute("Start");
                m_fStartVelX = float.Parse(VelxStart.Value);
                XAttribute VelxEnd = Velx.Attribute("End");
                m_fEndVelX = float.Parse(VelxEnd.Value);

                XElement Vely = xEmitter.Element("VelocityY");
                XAttribute VelyStart = Vely.Attribute("Start");
                m_fStartVelY = float.Parse(VelyStart.Value);
                XAttribute VelyEnd = Vely.Attribute("End");
                m_fEndVelY = float.Parse(VelyEnd.Value);

                XElement Rotation = xEmitter.Element("Rotation");
                XAttribute RotS = Rotation.Attribute("Start");
                m_fStartRotation = float.Parse(RotS.Value);
                XAttribute RotE = Rotation.Attribute("End");
                m_fEndRotation = float.Parse(RotE.Value);

                XElement Scale = xEmitter.Element("Scale");
                XAttribute ScaleSt = Scale.Attribute("Start");
                m_fStartScale = float.Parse(ScaleSt.Value);
                XAttribute ScaleEnd = Scale.Attribute("End");
                m_fEndScale = float.Parse(ScaleEnd.Value);

                XElement Position = xEmitter.Element("Position");
                XAttribute Posx = Position.Attribute("X");
                m_fPosX = float.Parse(Posx.Value);
                XAttribute Posy = Position.Attribute("Y");
                m_fPosY = float.Parse(Posx.Value);


                XElement ImageID = xEmitter.Element("ImageID");
                string temp = "..\\HeavyReinforcements\\Resource\\Graphics\\"  + ImageID.Value;
                NameOfParticle = System.IO.Path.GetFullPath(temp);
                m_nPartImageID = m_TM.LoadTexture(NameOfParticle);

                XElement SpawnShape = xEmitter.Element("SpawnShape");
                XAttribute SpawnSpVal = SpawnShape.Attribute("Value");
                m_nSpawnShape = int.Parse(SpawnSpVal.Value);

                XElement Alpha = xEmitter.Element("Alpha");
                XAttribute AlStart = Alpha.Attribute("Start");
                m_nStartAlpha = int.Parse(AlStart.Value);
                XAttribute AlEnd = Alpha.Attribute("End");
                m_nEndAlpha = int.Parse(AlEnd.Value);

                XElement Red = xEmitter.Element("Red");
                XAttribute RedS = Red.Attribute("Start");
                m_nStartR = int.Parse(RedS.Value);
                XAttribute RedE = Red.Attribute("End");
                m_nEndR = int.Parse(RedE.Value);

                XElement Green = xEmitter.Element("Green");
                XAttribute GreenS = Green.Attribute("Start");
                m_nStartG = int.Parse(GreenS.Value);
                XAttribute GreenE = Green.Attribute("End");
                m_nEndG = int.Parse(GreenE.Value);

                XElement Blue = xEmitter.Element("Blue");
                XAttribute BlueS = Blue.Attribute("Start");
                m_nStartB = int.Parse(BlueS.Value);
                XAttribute BlueE = Blue.Attribute("End");
                m_nEndB = int.Parse(BlueE.Value);

                int count = m_vTotalParticles.Count;

                for (int ParticleIndex = 0; ParticleIndex < count; ParticleIndex++)
                {
                    RemoveParticle(0);
                }
               
            }
        }
    }
}
